home *** CD-ROM | disk | FTP | other *** search
/ Amiga Magazin: Amiga-CD 1996 May & June / Amiga-CD 1996 #5-6.iso / kommunikation / ipdial / ipdial.c < prev    next >
C/C++ Source or Header  |  1996-03-22  |  23KB  |  1,135 lines

  1. /**
  2. ***  IPDial     Script program for initializing a SLIP connection
  3. ***  Copyright  (C)   1994    Jochen Wiedmann
  4. ***
  5. ***  This program is free software; you can redistribute it and/or modify
  6. ***  it under the terms of the GNU General Public License as published by
  7. ***  the Free Software Foundation; either version 2 of the License, or
  8. ***  (at your option) any later version.
  9. ***
  10. ***  This program is distributed in the hope that it will be useful,
  11. ***  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ***  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. ***  GNU General Public License for more details.
  14. ***
  15. ***  You should have received a copy of the GNU General Public License
  16. ***  along with this program; if not, write to the Free Software
  17. ***  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18. ***
  19. ***
  20. ***  This is the main part of the program.
  21. ***
  22. ***
  23. ***  Computer: Amiga 1200                       Compiler: Dice 3.01
  24. ***
  25. ***  Author:    Jochen Wiedmann
  26. ***             Am Eisteich 9
  27. ***             72555 Metzingen
  28. ***             Germany
  29. ***
  30. ***             Phone: (+0049) 7123 / 14881
  31. ***             Internet: wiedmann@neckar-alb.de
  32. ***
  33. ***
  34. ***  History:   V 1.1   23.11.94        Initial version
  35. ***
  36. ***             V 1.2   27.02.95        Added terminal mode
  37. ***                                     Now using ReadArgs() for
  38. ***                                     command line parsing.
  39. ***
  40. ***             V 1.3   09.03.95        Added environment variable
  41. ***                                     aupport to "send" command.
  42. ***                                     Added unit support.
  43. ***
  44. ***             V 1.4   21.04.95        Added "system" command.
  45. ***                                     Added environment variable
  46. ***                                     support to "echo" command.
  47. ***                                     Terminal mode now converts
  48. ***                                     LF to CR/LF, so that modem
  49. ***                                     recognizes commands.
  50. ***                                     (Let's hope, that will still
  51. ***                                     work for entering passwords. :-(
  52. ***
  53. ***             V 1.5   30.04.95        Added "scan" command.
  54. ***
  55. ***             V 1.6   26.06.95        "delay" command supporting
  56. ***                                     ticks; ParseString()
  57. ***                                     supporting octal characters;
  58. ***                                     "wait" command using
  59. ***                                     ParseString()
  60. ***                                     (All Suggested by Will Bow.)
  61. ***
  62. ***                                     Fixed bug in SerialSend():
  63. ***                                     *.io_Device = *.io_Unit
  64. ***
  65. ***             V 1.7   22.07.95        Added ECHO, RAW and EOF options
  66. ***                                     to "terminal" command.
  67. ***                                     (Suggested by Klaus Heinz.)
  68. ***
  69. ***                                     Added BAUD option to command
  70. ***                                     line.
  71. ***
  72. ***                                     Added "setvar" command.
  73. **/
  74.  
  75.  
  76.  
  77.  
  78.  
  79. #define VERSION     1
  80. #define REVISION    7
  81. #define VSTRING     "IPDial 1.7 (22.07.95)"
  82. #define VERSTAG     "\0$VER: IPDial 1.7 (22.07.95)"
  83.  
  84.  
  85.  
  86.  
  87.  
  88.  
  89. /**
  90. ***  Include files
  91. **/
  92. #ifndef IPDIAL_H
  93. #include "IPDial.h"
  94. #endif
  95.  
  96. #include <ctype.h>
  97. #include <clib/alib_protos.h>
  98.  
  99.  
  100.  
  101.  
  102.  
  103. /**
  104. ***  This structure describes one command. All commands are stored
  105. ***  in a table at the end of the file.
  106. **/
  107. struct ScriptLine;
  108. typedef VOID (*CommandFunc) (struct ScriptLine *);
  109. struct Command
  110. { CommandFunc Func;
  111.   STRPTR Name;
  112. };
  113.  
  114.  
  115.  
  116.  
  117.  
  118. /**
  119. ***  Each line of the script file is stored in a structure like below.
  120. **/
  121. struct ScriptLine
  122. { struct MinNode mn;
  123.   ULONG Num;
  124.   CommandFunc CommFunc;
  125.   STRPTR Label;
  126.   STRPTR Args;
  127. };
  128.  
  129.  
  130.  
  131.  
  132.  
  133. /**
  134. ***  Global variables
  135. **/
  136. LONG StatusVar;
  137.  
  138. struct MinList ScriptLineList;
  139.  
  140. struct ScriptLine *CurrentScriptLine;
  141.  
  142. const UBYTE VersTag [] = VERSTAG;
  143. const UBYTE VString [] = VSTRING;
  144.  
  145. ULONG EchoMode = FALSE;
  146. ULONG VerboseMode = FALSE;
  147.  
  148. STRPTR SerialDeviceName = NULL;
  149.  
  150. struct RDArgs *MainRDArgs = NULL;
  151.  
  152.  
  153.  
  154.  
  155.  
  156. /**
  157. ***  This function is used to skip blanks.
  158. **/
  159. STRPTR SkipBlanks(const UBYTE *ptr)
  160.  
  161. { while(*ptr == ' '  ||  *ptr == '\t')
  162.   { ++ptr;
  163.   }
  164.   return((STRPTR) ptr);
  165. }
  166.  
  167.  
  168.  
  169.  
  170.  
  171. /**
  172. ***  This function is used to parse a string for characters
  173. ***  like '\r' or '\n'. $VAR or ${VAR} may be used to insert
  174. ***  the value of environment variable VAR, $$ may be used to
  175. ***  insert the '$' character itself, likewise \\.
  176. ***
  177. ***  Returns a pointer to a string allocated with malloc().
  178. ***  It is the task of the caller, to free() this string.
  179. **/
  180. STRPTR ParseString(const UBYTE *ptr)
  181.  
  182. { STRPTR result;
  183.   STATIC APTR parseBuffer = NULL;
  184.  
  185.   /**
  186.   ***  Be sure, that buffer is valid.
  187.   **/
  188.   if (!parseBuffer  &&  !(parseBuffer = BufferCreate()))
  189.   { perror("malloc");
  190.     exit(10);
  191.   }
  192.  
  193.   /**
  194.   ***  Clear the buffer.
  195.   **/
  196.   BufferClear(parseBuffer);
  197.  
  198.   while(*ptr)
  199.   { if (*ptr == '\\')
  200.     { ++ptr;
  201.       switch(*ptr)
  202.       { case 'r':
  203.       BufferExtend(parseBuffer, (STRPTR) "\r", 1);
  204.       break;
  205.     case 'n':
  206.       BufferExtend(parseBuffer, (STRPTR) "\n", 1);
  207.       break;
  208.     case '0':
  209.     case '1':
  210.     case '2':
  211.     case '3':
  212.     case '4':
  213.     case '5':
  214.     case '6':
  215.     case '7':
  216.       { char c;
  217.  
  218.         c = *ptr - '0';
  219.         if (ptr[1] >= '0'  &&  ptr[1] <= '7')
  220.         { c = (c << 3) + *(++ptr) - '0';
  221.           if (ptr[1] >= '0'  &&  ptr[2] <= '7')
  222.           { c = (c << 3) + *(++ptr) - '0';
  223.           }
  224.         }
  225.         BufferExtend(parseBuffer, (STRPTR) &c, 1);
  226.       }
  227.       break;
  228.     default:
  229.       BufferExtend(parseBuffer, ptr, 1);
  230.       break;
  231.       }
  232.       ++ptr;
  233.     }
  234.     else if (*ptr == '$')
  235.     { ++ptr;
  236.       if (*ptr == '$')
  237.       { BufferExtend(parseBuffer, (STRPTR) "$", 1);
  238.     ++ptr;
  239.       }
  240.       else
  241.       { char *varName;
  242.     const char* varPtr;
  243.     size_t varLen = 0;
  244.  
  245.     if (*ptr == '{')
  246.     { ++ptr;
  247.       varPtr = (const char*) ptr;
  248.       while (*ptr && *ptr != '}')
  249.       { ++ptr;
  250.         ++varLen;
  251.       }
  252.      if (*ptr == '}')
  253.       { ++ptr;
  254.       }
  255.     }
  256.     else
  257.     { varPtr = (const char*) ptr;
  258.       while (*ptr  &&  isalnum(*ptr))
  259.       { ++ptr;
  260.         ++varLen;
  261.       }
  262.     }
  263.  
  264.     if (!(varName = malloc(varLen + 1)))
  265.     { perror("malloc");
  266.       exit(10);
  267.     }
  268.     strncpy(varName, varPtr, varLen);
  269.     varName[varLen] = '\0';
  270.  
  271.     if ((varPtr = getenv(varName)))
  272.     { BufferExtend(parseBuffer, (STRPTR) varPtr, strlen(varPtr));
  273.     }
  274.       }
  275.     }
  276.     else
  277.     { BufferExtend(parseBuffer, ptr, 1);
  278.       ++ptr;
  279.     }
  280.   }
  281.  
  282.   BufferExtend(parseBuffer, (STRPTR) "", 1);
  283.  
  284.   if (!(result = (STRPTR) strdup((char*) BufferBuffer(parseBuffer))))
  285.   { perror("malloc");
  286.     exit(10);
  287.   }
  288.  
  289.   return(result);
  290. }
  291.  
  292.  
  293.  
  294.  
  295.  
  296. /**
  297. ***  This is an empty function. Just to allow lines with labels only.
  298. **/
  299. VOID NoneFunc(struct ScriptLine *line)
  300.  
  301. {
  302. }
  303.  
  304.  
  305.  
  306.  
  307.  
  308. /**
  309. ***  This is the echo function.
  310. **/
  311. VOID EchoFunc(struct ScriptLine *line)
  312.  
  313. { STRPTR *args;
  314.   int i;
  315.  
  316.   if (!StrReadArgs(line->Args, (LONG *) &args, (STRPTR) "ARGS/M"))
  317.   { fprintf(stderr, "Line %ld: Argument or memory error\n", line->Num);
  318.     exit(10);
  319.   }
  320.  
  321.   for(i = 0;  *args;  ++i, ++args)
  322.   { char *str;
  323.  
  324.     if (i)
  325.     { putchar(' ');
  326.     }
  327.     str = (char*) ParseString(*args);
  328.     fputs((char *) str, stdout);
  329.     fflush(stdout);
  330.     free(str);
  331.   }
  332. }
  333.  
  334.  
  335.  
  336.  
  337.  
  338. /**
  339. ***  This is the device function.
  340. **/
  341. VOID DeviceFunc(struct ScriptLine *line)
  342.  
  343. { struct
  344.   { STRPTR Device;
  345.     STRPTR Protocol;
  346.     LONG *Unit;
  347.   } args;
  348.  
  349.   if (SerialDeviceName)
  350.   { fprintf(stderr, "Line %ld: Device already open, ignoring.\n", line->Num);
  351.   }
  352.  
  353.   args.Unit = NULL;
  354.   args.Device = NULL;
  355.   args.Protocol = NULL;
  356.  
  357.   if (!StrReadArgs(line->Args, (LONG *) &args,
  358.            (STRPTR) "DEVICE,PROTOCOL,UNIT/K/N"))
  359.   { fprintf(stderr, "Line %ld: Argument or memory error\n", line->Num);
  360.     exit(10);
  361.   }
  362.  
  363.   if (!args.Device)
  364.   { fprintf(stderr, "Line %ld: Missing device name.\n", line->Num);
  365.     exit(10);
  366.   }
  367.   if (!(SerialDeviceName = (STRPTR) strdup((char *) args.Device)))
  368.   { perror("malloc");
  369.     exit(10);
  370.   }
  371.  
  372.   if (VerboseMode)
  373.   { printf("Opening %s.\n", args.Device);
  374.   }
  375.  
  376.   if (!SerialOpen(args.Device, args.Protocol, args.Unit ? *args.Unit : 0))
  377.   { fprintf(stderr, "Line %ld: Unknown protocol.\n", line->Num);
  378.     exit(10);
  379.   }
  380. }
  381.  
  382.  
  383.  
  384.  
  385.  
  386. /**
  387. ***  This function is used to set the serial.device parameters.
  388. **/
  389. VOID SetFunc(struct ScriptLine *line)
  390.  
  391. { struct
  392.   { ULONG *Baud;
  393.     ULONG *DataBits;
  394.     ULONG *StopBits;
  395.     ULONG *BufSize;
  396.     STRPTR Parity;
  397.     STRPTR Protocol;
  398.   } args;
  399.  
  400.   if (!SerialDeviceName)
  401.   { fprintf(stderr, "Line %ld: Must open serial.device first.\n", line->Num);
  402.     exit(10);
  403.   }
  404.  
  405.   args.Baud = NULL;
  406.   args.DataBits = NULL;
  407.   args.StopBits = NULL;
  408.   args.BufSize = NULL;
  409.   args.Parity = NULL;
  410.   args.Protocol = NULL;
  411.  
  412.   if (!(StrReadArgs(line->Args, (LONG *) &args,
  413.             (STRPTR) "BAUD/K/N,DATABITS/K/N,STOPBITS/K/N,BUFSIZE/K/N,"
  414.                  "PARITY/K,PROTOCOL/K")))
  415.   { fprintf(stderr, "Line %ld: Argument or memory error.\n", line->Num);
  416.     exit(10);
  417.   }
  418.  
  419.   if (args.Baud)
  420.   { SerialSetBaud(*args.Baud);
  421.   }
  422.   if (args.DataBits)
  423.   { SerialSetDataBits(*args.DataBits);
  424.   }
  425.   if (args.StopBits)
  426.   { SerialSetStopBits(*args.StopBits);
  427.   }
  428.   if (args.BufSize)
  429.   { SerialSetBufSize(*args.BufSize);
  430.   }
  431.   if (args.Parity)
  432.   { if (!SerialSetParity(args.Parity))
  433.     { fprintf(stderr, "Line %ld: Unknown parity.\n", line->Num);
  434.       exit(10);
  435.     }
  436.   }
  437.   if (args.Protocol)
  438.   { if (!SerialSetProtocol(args.Protocol))
  439.     { fprintf(stderr, "Line %ld: Unknown protocol.\n", line->Num);
  440.       exit(10);
  441.     }
  442.   }
  443.  
  444.   if (VerboseMode)
  445.   { printf("%s Parameters modified:\n\n", SerialDeviceName);
  446.     SerialShowParms();
  447.   }
  448. }
  449.  
  450.  
  451.  
  452.  
  453.  
  454. /**
  455. ***  This function shows the serial.device parameters.
  456. **/
  457. VOID ShowParmsFunc(struct ScriptLine *line)
  458.  
  459. { if (!SerialDeviceName)
  460.   { fprintf(stderr, "Line %ld: Must open serial.device first.\n", line->Num);
  461.     exit(10);
  462.   }
  463.  
  464.   printf("%s Parameters:\n\n", SerialDeviceName);
  465.   SerialShowParms();
  466. }
  467.  
  468.  
  469.  
  470.  
  471.  
  472. /**
  473. ***  This function sends a string to the serial.device.
  474. **/
  475. VOID SendFunc(struct ScriptLine *line)
  476.  
  477. { STRPTR *args;
  478.  
  479.   if (!SerialDeviceName)
  480.   { fprintf(stderr, "Line %ld: Must open serial.device first.\n", line->Num);
  481.     exit(10);
  482.   }
  483.  
  484.   if (!StrReadArgs(line->Args, (LONG *) &args, (STRPTR) "ARGS/M"))
  485.   { fprintf(stderr, "Line %ld: Argument or memory error\n", line->Num);
  486.     exit(10);
  487.   }
  488.  
  489.   if (VerboseMode)
  490.   { printf("\nSending ");
  491.   }
  492.  
  493.   for(;  *args;  args++)
  494.   { STRPTR send = ParseString(*args);
  495.  
  496.     SerialSend(send, strlen((char *) send));
  497.     free(send);
  498.   }
  499.  
  500.   if (VerboseMode)
  501.   { printf("\n");
  502.   }
  503. }
  504.  
  505.  
  506.  
  507.  
  508.  
  509. /**
  510. ***  This is similar to "if".
  511. **/
  512. VOID DoGoto(STRPTR Label, int Num)
  513.  
  514. { struct ScriptLine *sl;
  515.  
  516.   for(sl = (struct ScriptLine *) ScriptLineList.mlh_Head;
  517.         sl->mn.mln_Succ;
  518.         sl = (struct ScriptLine *) sl->mn.mln_Succ)
  519.   { if (sl->Label  &&  strcmp((char *) sl->Label, (char *) Label) == 0)
  520.     { CurrentScriptLine = (struct ScriptLine *) sl->mn.mln_Pred;
  521.       return;
  522.     }
  523.   }
  524.  
  525.   fprintf(stderr, "Line %d: Unknown label.\n", Num);
  526.   exit(10);
  527. }
  528. VOID OnFunc(struct ScriptLine *line)
  529.  
  530. { STRPTR ptr = line->Args;
  531.  
  532.   if (strnicmp((char *) ptr, "status", 6) == 0)
  533.   { ptr = SkipBlanks(ptr+6);
  534.     if (strnicmp((char *) ptr, "goto", 4) == 0)
  535.     { STRPTR *labels;
  536.       int i;
  537.  
  538.       if (!StrReadArgs(ptr+4, (LONG *) &labels, (STRPTR) "LABELS/M"))
  539.       { fprintf(stderr, "Line %ld: Memory error.\n", line->Num);
  540.     exit(10);
  541.       }
  542.       for (i = -1;  *labels;  ++i, ++labels)
  543.       { if (i == StatusVar)
  544.     { DoGoto(*labels, line->Num);
  545.       return;
  546.     }
  547.       }
  548.       return;
  549.     }
  550.   }
  551.  
  552.   fprintf(stderr, "Line %ld: Condition syntax.", line->Num);
  553.   exit(10);
  554. }
  555.  
  556.  
  557.  
  558.  
  559.  
  560. /**
  561. ***  This function waits for certain strings.
  562. **/
  563. VOID WaitFunc(struct ScriptLine *line)
  564.  
  565. { struct
  566.   { STRPTR *WaitArgs;
  567.     ULONG *TimeOut;
  568.   } args;
  569.   STRPTR* parsedArgs;
  570.   LONG TimeOut;
  571.   int i = 0;
  572.  
  573.   if (!SerialDeviceName)
  574.   { fprintf(stderr, "Line %ld: Must open serial.device first.\n", line->Num);
  575.     exit(10);
  576.   }
  577.  
  578.   args.WaitArgs = NULL;
  579.   args.TimeOut = NULL;
  580.  
  581.   if (!(StrReadArgs(line->Args, (LONG *) &args, (STRPTR) "ARGS/M,TIMEOUT/N/K")))
  582.   { fprintf(stderr, "Line %ld: Argument or memory error.\n", line->Num);
  583.     exit(10);
  584.   }
  585.  
  586.   if (!args.WaitArgs)
  587.   { fprintf(stderr, "Line %ld: Missing argument.\n", line->Num);
  588.     exit(10);
  589.   }
  590.   if (!args.TimeOut)
  591.   { fprintf(stderr, "Line %ld: Missing timeout argument.\n", line->Num);
  592.     exit(10);
  593.   }
  594.   TimeOut = *args.TimeOut;
  595.  
  596.  
  597.   while (args.WaitArgs[i])
  598.   { ++i;
  599.   }
  600.  
  601.   if (!(parsedArgs = malloc(sizeof(STRPTR) * (i+1))))
  602.   { perror("malloc");
  603.     exit(10);
  604.   }
  605.  
  606.   for (i = 0;  args.WaitArgs[i];  i++)
  607.   { parsedArgs[i] = ParseString(args.WaitArgs[i]);
  608.   }
  609.   parsedArgs[i] = NULL;
  610.  
  611.   StatusVar = SerialWait(parsedArgs, TimeOut);
  612. }
  613.  
  614.  
  615.  
  616.  
  617.  
  618. /**
  619. ***  The delay function waits for a certain amount of time.
  620. **/
  621. VOID DelayFunc(struct ScriptLine *line)
  622.  
  623. { ULONG tics = (int) (atof((char *) line->Args) * 50.0);
  624.  
  625.   if (tics == 0)
  626.   { fprintf(stderr, "Line %ld: Missing argument.\n", line->Num);
  627.     exit(10);
  628.   }
  629.  
  630.   Delay(tics);
  631. }
  632.  
  633.  
  634.  
  635.  
  636.  
  637. /**
  638. ***  And this is the Exit function.
  639. **/
  640. VOID ExitFunc(struct ScriptLine *line)
  641.  
  642. { LONG result = atol((char *) line->Args);
  643.  
  644.   exit(result);
  645. }
  646.  
  647.  
  648.  
  649.  
  650.  
  651. /**
  652. ***  The Goto command
  653. **/
  654. VOID GotoFunc(struct ScriptLine *line)
  655.  
  656. { STRPTR Label;
  657.  
  658.   if (!(StrReadArgs(line->Args, (LONG *) &Label, (STRPTR) "LABEL/A")))
  659.   { fprintf(stderr, "Line %ld: Missing argument or memory error.\n",
  660.         line->Num);
  661.     exit(10);
  662.   }
  663.   DoGoto(Label, line->Num);
  664. }
  665.  
  666.  
  667.  
  668.  
  669.  
  670. /**
  671. ***  This function enters terminal mode.
  672. **/
  673. VOID TermFunc(struct ScriptLine *line)
  674.  
  675. { struct
  676.   { STRPTR eof;
  677.     ULONG noecho;
  678.     ULONG raw;
  679.   } args;
  680.  
  681.   args.eof = NULL;
  682.   args.noecho = FALSE;
  683.   args.raw = FALSE;
  684.  
  685.   if (!StrReadArgs(line->Args, (LONG *) &args, (STRPTR) "EOF,NOECHO/S,RAW/S"))
  686.   { fprintf(stderr, "Line %ld: Argument or memory error\n", line->Num);
  687.     exit(10);
  688.   }
  689.  
  690.   if (args.eof) {
  691.       args.eof = ParseString(args.eof);
  692.   }
  693.   SerialTerminal(args.eof, !args.noecho, !args.raw);
  694. }
  695.  
  696.  
  697.  
  698.  
  699.  
  700. /**
  701. ***  Execute external commands.
  702. **/
  703. VOID SystemFunc(struct ScriptLine *line)
  704.  
  705. { STRPTR *args;
  706.   int i, result;
  707.   char *cmd;
  708.   STATIC APTR systemBuffer = NULL;
  709.  
  710.   /**
  711.   ***  Initialize buffer.
  712.   **/
  713.   if (!systemBuffer  &&  !(systemBuffer = BufferCreate()))
  714.   { perror("malloc");
  715.     exit(10);
  716.   }
  717.   BufferClear(systemBuffer);
  718.  
  719.  
  720.   if (!StrReadArgs(line->Args, (LONG *) &args, (STRPTR) "ARGS/M"))
  721.   { fprintf(stderr, "Line %ld: Argument or memory error\n", line->Num);
  722.     exit(10);
  723.   }
  724.  
  725.   for(i = 0;  *args;  ++i, ++args)
  726.   { char *str;
  727.  
  728.     if (i)
  729.     { BufferExtend(systemBuffer, (STRPTR) " ", 1);
  730.     }
  731.     str = (char*) ParseString(*args);
  732.     BufferExtend(systemBuffer, (STRPTR) str, strlen(str));
  733.     free(str);
  734.   }
  735.   cmd = (char*) BufferBuffer(systemBuffer);
  736.  
  737.   if (VerboseMode)
  738.   { printf("Executing command: \"%s\"\n", cmd);
  739.   }
  740.   result = system(cmd);
  741.   if (result)
  742.   { if (result > 1  &&  result < 10)  /* Warning */
  743.     { if (VerboseMode)
  744.       { printf("Returned %d.\n", result);
  745.       }
  746.     }
  747.     else
  748.     { printf("Error: Command \"%s\" returned %d.\n", cmd, result);
  749.       exit(result);
  750.     }
  751.   }
  752. }  
  753.  
  754.  
  755.  
  756.  
  757.  
  758. /**
  759. ***  Scan the buffer received by the last "wait" command.
  760. **/
  761. VOID ScanFunc(struct ScriptLine *line)
  762.  
  763. { struct
  764.   { STRPTR format;
  765.     ULONG global;
  766.     ULONG save;
  767.   } args;
  768.   ULONG flags;
  769.  
  770.   args.format = NULL;
  771.   args.global = FALSE;
  772.   args.save = FALSE;
  773.  
  774.   if (!(StrReadArgs(line->Args, (LONG *) &args,
  775.             (STRPTR) "FORMAT/A,GLOBAL/S,SAVE/S")))
  776.   { fprintf(stderr, "Line %ld: Argument or memory error.\n", line->Num);
  777.     exit(10);
  778.   }
  779.  
  780.   flags = 0;
  781.   if (args.save)
  782.   { args.global = TRUE;
  783.     flags |= GVF_SAVE_VAR;
  784.   }
  785.   if (args.global)
  786.   { flags |= GVF_GLOBAL_ONLY;
  787.   }
  788.   else
  789.   { flags |= GVF_LOCAL_ONLY;
  790.   }
  791.  
  792.   StatusVar = Vsscanf(SerialWaitBuffer(), args.format, flags);
  793. }
  794.  
  795.  
  796.  
  797.  
  798. /**
  799. ***  The SetVar command
  800. **/
  801. void SetVarFunc(struct ScriptLine *line)
  802.  
  803. { struct {
  804.     STRPTR name;
  805.     STRPTR value;
  806.     ULONG global;
  807.     ULONG save;
  808.   } args;
  809.   int flags;
  810.  
  811.   args.name = NULL;
  812.   args.value = NULL;
  813.   args.global = FALSE;
  814.   args.save = FALSE;
  815.  
  816.   if (!(StrReadArgs(line->Args, (LONG *) &args,
  817.             (STRPTR) "NAME/A,VALUE/A,LOCALONLY/S,GLOBALONLY/S,SAVE/S")))
  818.   { fprintf(stderr, "Line %ld: Missing argument or memory error.\n",
  819.         line->Num);
  820.     exit(10);
  821.   }
  822.  
  823.   flags = 0;
  824.   if (args.save) {
  825.       flags |= GVF_SAVE_VAR;
  826.       args.global = TRUE;
  827.   }
  828.   if (args.global) {
  829.       flags |= GVF_GLOBAL_ONLY;
  830.   } else {
  831.       flags |= GVF_LOCAL_ONLY;
  832.   }
  833.  
  834.   setvar(args.name, args.value, LV_VAR|flags);
  835. }
  836.  
  837.  
  838.  
  839.  
  840. /**
  841. ***  This is the command table.
  842. **/
  843. struct Command CommandTab[] =
  844. { { EchoFunc,       (STRPTR) "echo"         },
  845.   { DeviceFunc,     (STRPTR) "device"       },
  846.   { SetFunc,        (STRPTR) "set"          },
  847.   { ShowParmsFunc,  (STRPTR) "showparms"    },
  848.   { SendFunc,       (STRPTR) "send"         },
  849.   { OnFunc,         (STRPTR) "on"           },
  850.   { WaitFunc,       (STRPTR) "wait"         },
  851.   { DelayFunc,      (STRPTR) "delay"        },
  852.   { ExitFunc,       (STRPTR) "exit"         },
  853.   { GotoFunc,       (STRPTR) "goto"         },
  854.   { TermFunc,       (STRPTR) "terminal"     },
  855.   { SystemFunc,     (STRPTR) "system"       },
  856.   { ScanFunc,       (STRPTR) "scan"         },
  857.   { SetVarFunc,     (STRPTR) "setvar"       },
  858.   { NULL,           NULL                    }
  859. };
  860.  
  861.  
  862.  
  863.  
  864.  
  865. /**
  866. ***  This function is used to process the file. Rather easy,
  867. ***  isn't it? :-)
  868. **/
  869. VOID ProcessFile(VOID)
  870.  
  871. { for(CurrentScriptLine = (struct ScriptLine *) ScriptLineList.mlh_Head;
  872.       CurrentScriptLine->mn.mln_Succ;
  873.       CurrentScriptLine = (struct ScriptLine *) CurrentScriptLine->mn.mln_Succ)
  874.   { (*CurrentScriptLine->CommFunc)(CurrentScriptLine);
  875.   }
  876. }
  877.  
  878.  
  879.  
  880.  
  881.  
  882. /**
  883. ***  This function reads and parses the file.
  884. **/
  885. VOID ParseFile(STRPTR file)
  886.  
  887. { FILE *fp;
  888.   STATIC UBYTE buffer[4096];
  889.   ULONG linenum = 0;
  890.   ULONG success = TRUE;
  891.  
  892.   if (!(fp = fopen((char *) file, "r")))
  893.   { fprintf(stderr, "Could not open %s for reading.\n", file);
  894.     exit(10);
  895.   }
  896.  
  897.   NewList((struct List *) &ScriptLineList);
  898.  
  899.   while(fgets((char *) buffer, sizeof(buffer), fp))
  900.   { ULONG len = strlen((char *) buffer);
  901.     STRPTR line;
  902.     STRPTR Label = NULL;
  903.     CommandFunc CommFunc;
  904.  
  905.     ++linenum;
  906.  
  907.     if (buffer[len-1] != '\n')
  908.     { fprintf(stderr, "Line %ld too long.\n", linenum);
  909.       exit(10);
  910.     }
  911.  
  912.     if (!(line = malloc(len+1)))
  913.     { perror("malloc");
  914.       exit(10);
  915.     }
  916.     strcpy((char*) line, (char*) buffer);
  917.     line = SkipBlanks(line);
  918.  
  919.     /**
  920.     ***  Check for a label
  921.     **/
  922.     { STRPTR ptr = line;
  923.  
  924.       if (isalpha(*ptr))
  925.       { do
  926.     { ++ptr;
  927.     }
  928.     while(isalnum(*ptr));
  929.  
  930.     if (*ptr == ':')
  931.     { *ptr = '\0';
  932.       Label = line;
  933.       line = SkipBlanks(ptr+1);
  934.     }
  935.       }
  936.     }
  937.  
  938.     /**
  939.     ***  Check for empty line or comment line
  940.     **/
  941.     if (*line == ';'  ||  *line == '\r'  ||  *line == '\n')
  942.     { CommFunc = NoneFunc;
  943.       if (!Label)
  944.       { continue;
  945.       }
  946.     }
  947.  
  948.     /**
  949.     ***  If no empty line: Check for command
  950.     **/
  951.     else
  952.     { struct Command *comm;
  953.  
  954.       for (comm = &CommandTab[0];  comm->Func;  ++comm)
  955.       { ULONG len = strlen((char *) comm->Name);
  956.  
  957.     if (strnicmp((char *) comm->Name, (char *) line, len) == 0  &&
  958.         (line[len] == ' '  ||  line[len] == '\t'  ||
  959.          line[len] == '\r' ||  line[len] == '\n'))
  960.     { line = SkipBlanks(line+len);
  961.       CommFunc = comm->Func;
  962.       break;
  963.     }
  964.       }
  965.  
  966.       if (!comm->Func)
  967.       { fprintf(stderr, "Line %ld: Unknown command.\n", linenum);
  968.     success = FALSE;
  969.       }
  970.     }
  971.  
  972.     /**
  973.     ***  Allocate a new scriptline structure.
  974.     **/
  975.     { struct ScriptLine *sl;
  976.  
  977.       if (!(sl = malloc(sizeof(*sl))))
  978.       { perror("malloc");
  979.     exit(10);
  980.       }
  981.  
  982.       AddTail((struct List *) &ScriptLineList, (struct Node *) sl);
  983.       sl->Num = linenum;
  984.       sl->CommFunc = CommFunc;
  985.       sl->Args = line;
  986.       sl->Label = Label;
  987.     }
  988.   }
  989.  
  990.   if (ferror(fp))
  991.   { perror("fgets");
  992.     exit(10);
  993.   }
  994.  
  995.   if (!success)
  996.   { exit(10);
  997.   }
  998.  
  999.   fclose(fp);
  1000. }
  1001.  
  1002.  
  1003.  
  1004.  
  1005.  
  1006. /**
  1007. ***  This is the Cleanup() function, called, when the program terminates.
  1008. **/
  1009. VOID Cleanup(VOID)
  1010.  
  1011. { SerialCleanup();
  1012.   StrReadArgsFree();
  1013.   if (MainRDArgs)
  1014.   { FreeArgs(MainRDArgs);
  1015.   }
  1016. }
  1017.  
  1018.  
  1019.  
  1020.  
  1021.  
  1022. /**
  1023. ***  This function hints about the GPL.
  1024. **/
  1025. VOID ShowGPL(FILE *fp)
  1026.  
  1027. { fprintf(fp, "This program is governed by the terms and conditions of the\n");
  1028.   fprintf(fp, "GNU General Public License. A copy should have come with\n");
  1029.   fprintf(fp, "this distribution. (See the file COPYING.) In that license\n");
  1030.   fprintf(fp, "it is made clear that you are welcome to redistribute either\n");
  1031.   fprintf(fp, "verbatim or modified copies of the program and the documentation\n");
  1032.   fprintf(fp, "under certain conditions. Further you are told that this program\n");
  1033.   fprintf(fp, "comes with ABSOLUTELY NO WARRANTY!\n");
  1034. }
  1035.  
  1036.  
  1037.  
  1038.  
  1039.  
  1040. /**
  1041. ***  This function displays the Usage() message.
  1042. **/
  1043. VOID Usage(VOID)
  1044.  
  1045. { fprintf(stderr, "Usage: IPDial SCRIPT,DEVICE/K,PROTOCOL/K,TERMINAL/S,ECHO/S,VERBOSE/S,HELP/S\n\n");
  1046.   fprintf(stderr, "\tSCRIPT:    Script file to execute.\n");
  1047.   fprintf(stderr, "\tDEVICE:    Device to use (default serial.device)\n");
  1048.   fprintf(stderr, "\tPROTOCOL:  Protocol to use; XONXOFF, 7WIRE (default) or NONE)\n");
  1049.   fprintf(stderr, "\tUNIT:      Unit to use (default 0)\n");
  1050.   fprintf(stderr, "\tECHO:      Show modems replies.\n");
  1051.   fprintf(stderr, "\tVERBOSE:   Be verbose.\n\n");
  1052.   fprintf(stderr, "\tTERMINAL:  Run in terminal mode.\n");
  1053.   fprintf(stderr, "\tHELP:      Print this message.\n");
  1054.   fprintf(stderr, "\n\n%s  @ 1994 by Jochen Wiedmann\n\n", VString);
  1055.   ShowGPL(stderr);
  1056.   exit(5);
  1057. }
  1058.  
  1059.  
  1060.  
  1061.  
  1062.  
  1063. /**
  1064. ***  This is main().
  1065. **/
  1066. int main(int argc, char *argv[])
  1067.  
  1068. { struct
  1069.   { STRPTR file;
  1070.     STRPTR device;
  1071.     STRPTR protocol;
  1072.     LONG *unit;
  1073.     LONG *baud;
  1074.     ULONG terminal;
  1075.     ULONG help;
  1076.     ULONG echo;
  1077.     ULONG verbose;
  1078.     ULONG raw;
  1079.   } args;
  1080.  
  1081.   args.file = NULL;
  1082.   args.device = (STRPTR) "serial.device";
  1083.   args.protocol = (STRPTR) "7wire";
  1084.   args.unit = NULL;
  1085.   args.baud = NULL;
  1086.   args.terminal = FALSE;
  1087.   args.echo = FALSE;
  1088.   args.verbose = FALSE;
  1089.   args.help = FALSE;
  1090.   args.raw = FALSE;
  1091.  
  1092.   if (!argc)    /*  No WB handling.     */
  1093.   { exit(-1);
  1094.   }
  1095.  
  1096.   if (atexit(Cleanup))
  1097.   { fprintf(stderr, "Memory error.\n");
  1098.     exit(20);
  1099.   }
  1100.  
  1101.   if (!(MainRDArgs = ReadArgs((STRPTR) "SCRIPT,DEVICE/K,PROTOCOL/K,"
  1102.                   "UNIT/K/N,BAUD/K/N,TERMINAL/S,"
  1103.                   "HELP/S,ECHO/S,VERBOSE/S,RAW/S",
  1104.                   (LONG *) &args, NULL)))
  1105.   { fprintf(stderr, "Cannot parse command line.\n");
  1106.   }
  1107.  
  1108.   if (args.help  ||
  1109.       (!args.file  &&  !args.terminal))
  1110.   { Usage();
  1111.   }
  1112.  
  1113.   EchoMode = args.echo;
  1114.   if (args.verbose)
  1115.   { VerboseMode = TRUE;
  1116.     printf("%s  @ 1994 by Jochen Wiedmann\n\n", VString);
  1117.     ShowGPL(stdout);
  1118.     printf("\n\n");
  1119.   }
  1120.  
  1121.   if (args.terminal)
  1122.   { SerialOpen(args.device, args.protocol, args.unit ? *args.unit : 0);
  1123.     if (args.baud)
  1124.     { SerialSetBaud(*args.baud);
  1125.     }
  1126.     SerialTerminal(NULL, TRUE, !args.raw);
  1127.   }
  1128.   else if (args.file)
  1129.   { ParseFile(args.file);
  1130.     ProcessFile();
  1131.   }
  1132.  
  1133.   exit(0);
  1134. }
  1135.